﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RbmlVisualizer.Data;
using RbmlVisualizer.Data.Blocks;
using RbmlVisualizer.Data.Link;

namespace RbmlVisualizer.Utilities
{
    public static class BlockTypeConverter
    {
        private const string _generalizationRoleString = "Generalization Role";
        private const string _dependencyRoleString = "Dependency Role";
        private const string _associationRoleString = "Association Role";

        public static string ConvertFromBlockTypeToString(BlockType blockType)
        {
            switch (blockType)
            {
                case BlockType.Generalization:
                    return _generalizationRoleString;
                case BlockType.Dependency:
                    return _dependencyRoleString;
                case BlockType.Association:
                    return _associationRoleString;
                default:
                    throw new ArgumentOutOfRangeException("blockType");
            }
        }

        public static BlockType ConvertFromStringToBlockType(string blockString)
        {
            if (!string.IsNullOrEmpty(blockString))
            {
                if (blockString.Contains(_associationRoleString))
                    return BlockType.Association;

                if (blockString.Contains(_dependencyRoleString))
                    return BlockType.Dependency;

                if (blockString.Contains(_generalizationRoleString))
                    return BlockType.Generalization;
            }

            return BlockType.None;
        }

        public static BlockLinkDecorator GetMatchingUmlBlockEnd(BlockLinkDecorator rbmlLinkEndDecorator)
        {
            switch (rbmlLinkEndDecorator)
            {
                case BlockLinkDecorator.Supplier:
                    return BlockLinkDecorator.Use;
                case BlockLinkDecorator.General:
                    return BlockLinkDecorator.Extend;
                default:
                    return BlockLinkDecorator.None;
            }
        }

        internal static Tuple<BlockLinkDecorator, BlockLinkDecorator> ConvertLinkToBlockLinkDecorators(ILink link, Data.ClassDiagramType diagramType)
        {
            if (diagramType == ClassDiagramType.Rbml)
                return new Tuple<BlockLinkDecorator, BlockLinkDecorator>(ConvertLinkEndLabelToBlockLinkDecorator(link.LinkEndLabel1), ConvertLinkEndLabelToBlockLinkDecorator(link.LinkEndLabel2));
            else
                return new Tuple<BlockLinkDecorator, BlockLinkDecorator>(ConvertLinkEndTypeToBlockLinkDecorator(link.LinkEndType1), ConvertLinkEndTypeToBlockLinkDecorator(link.LinkEndType2));
        }

        private static BlockLinkDecorator ConvertLinkEndTypeToBlockLinkDecorator(LinkEndType linkEndType)
        {
            switch (linkEndType)
            {
                case LinkEndType.Extends:
                    return BlockLinkDecorator.Extend;
                case LinkEndType.Composition:
                case LinkEndType.Agregation:
                case LinkEndType.Arrow:
                    return BlockLinkDecorator.Use;
                case LinkEndType.Plus:
                case LinkEndType.None:
                case LinkEndType.Square:
                    return BlockLinkDecorator.None;
                default:
                    throw new ArgumentOutOfRangeException("linkEndType");
            }

        }


        private static BlockLinkDecorator ConvertLinkEndLabelToBlockLinkDecorator(string linkEndLabel)
        {
            const string general = "general";
            const string special = "special";
            const string supplier = "supplier";
            const string client = "client";

            if (string.IsNullOrEmpty(linkEndLabel))
                return BlockLinkDecorator.None;

            var label = linkEndLabel.ToLower();

            switch (label)
            {
                case general:
                    return BlockLinkDecorator.General;
                case special:
                    return BlockLinkDecorator.Special;
                case supplier:
                    return BlockLinkDecorator.Supplier;
                case client:
                    return BlockLinkDecorator.Client;
            }

            return BlockLinkDecorator.None;
        }

        internal static BlockType ConvertLinkToBlockType(ILink link, ClassDiagramType diagramType)
        {
            if (diagramType == ClassDiagramType.Rbml)
                return ConvertFromStringToBlockType(link.Label);

            if (diagramType == ClassDiagramType.Uml)
                return ConvertFromLinkTypeToBlockType(link);

            return BlockType.None;
        }

        private static BlockType ConvertFromLinkTypeToBlockType(ILink link)
        {
            if (link.HasLinkEndType(LinkEndType.Arrow))
                return BlockType.Dependency;

            if (link.HasLinkEndType(LinkEndType.Extends))
                return BlockType.Generalization;

            if (link.HasAnyLinkEndType(new[] { LinkEndType.Composition, LinkEndType.Agregation, LinkEndType.None }))
                return BlockType.Association;

            return BlockType.None;
        }
    }
}
